﻿using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using LayoutViewer.Views;
using MQTTnet;
using MQTTnet.Client;
using MQTTnet.Packets;
using Newtonsoft.Json;
using SkiaSharp;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace LayoutViewer.Models.Helpers
{
    internal class ATHelper : BaseHelper
    {
        internal override Action<Bitmap, MoveCategory> OnSucceed { get; set; }
        internal override Action<string> OnFailed { get; set; }

        private IMqttClient client;

        private string deviceName = "null";

        internal static async Task<ATHelper> Create(string ip)
        {
            var result = new ATHelper();
            try
            {
                var mqttClientOptions = new MqttClientOptionsBuilder()
                    .WithTcpServer((op) =>
                    {
                        op.Server = ip;
                        op.BufferSize = 1024 * 1024 * 10;
                    })
                    .WithKeepAlivePeriod(TimeSpan.FromMinutes(6))
                    .Build();

                var mqttFactory = new MqttFactory();
                result.client = mqttFactory.CreateMqttClient();

                result.client.ApplicationMessageReceivedAsync += result.ApplicationMessageReceived;
                result.client.ConnectedAsync += async (e) =>
                {

                    await result.client.SubscribeAsync(new MqttClientSubscribeOptions
                    {
                        TopicFilters = new()
                        {
                            new MqttTopicFilter{ Topic = "server/init" },
                            new MqttTopicFilter{ Topic = "server/screen-shot" },
                            new MqttTopicFilter{ Topic = "server/layout-dump" }
                        }
                    });

                    await result.client.PublishStringAsync("client/init");
                };

                result.client.DisconnectedAsync += async (e) =>
                {
                    await result.client.UnsubscribeAsync(new MqttClientUnsubscribeOptions
                    {
                        TopicFilters = new()
                        {
                            "server/init",
                            "server/logging",
                        }
                    });
                    result.client.Dispose();
                };

                await result.client.ConnectAsync(mqttClientOptions, CancellationToken.None);
                return result;
            }
            catch (Exception ex)
            {
                _ = AlertDialog.ShowAsync($"AT连接模式初始化失败: {ex.Message}");
                return null;
            }
        }



        private Task ApplicationMessageReceived(MqttApplicationMessageReceivedEventArgs e)
        {
            var pack = PackData.Parse(e.ApplicationMessage.Payload);
            if (pack is null) return Task.CompletedTask;
            switch (e.ApplicationMessage.Topic)
            {
                case "server/init":
                    this.deviceName = pack.Description!;
                    break;
                case "server/layout-dump":
                    try
                    {
                        if (pack.Key == "successed")
                        {
                            var imgLen = pack.Buffer!.ToInt32();
                            var imgBytes = pack.Buffer!.AsSpan(4, imgLen).ToArray();

                            var jsLen = pack.Buffer!.ToInt32(4 + imgLen);
                            var jsBytes = pack.Buffer!.AsSpan(4 + imgLen + 4, jsLen).ToArray();

                            using var sKBitmap = SKBitmap.Decode(imgBytes);
                            var pxFormat = sKBitmap.ColorType == SKColorType.Rgba8888 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888;
                            var bitmap = new Bitmap(pxFormat, AlphaFormat.Opaque, sKBitmap.GetPixels(), new PixelSize(sKBitmap.Width, sKBitmap.Height), new Vector(96, 96), sKBitmap.RowBytes);

                            var js = Encoding.UTF8.GetString(jsBytes);
                            var layoutInfo = JsonConvert.DeserializeObject<MoveCategory>(js);

                            this.OnSucceed?.Invoke(bitmap, layoutInfo!);
                        }
                        else
                            this.OnFailed?.Invoke(pack.Description!);
                    }
                    catch (Exception ex)
                    {
                        this.OnFailed?.Invoke($"获取布局失败: {ex.Message}");
                    }
                    break;
            }
            return Task.CompletedTask;
        }

        internal override async Task<List<KeyValuePair<int, string>>> GetList()
        {
            return await Task.Run(() =>
            {
                var result = new List<KeyValuePair<int, string>>
                 {
                     new KeyValuePair<int, string>(key: 0, value: this.deviceName)
                 };
                return result;
            });
        }

        internal override void LayoutDump(string _)
        {
            if (this.client is null || !this.client.IsConnected)
            {
                throw new Exception("已断开连接!");
            }
            var pack = Stick.MakePackData("...");
            this.client.PublishBinaryAsync("client/layout-dump", pack);
        }

        internal override void Close()
        {
            try
            {
                this.client?.Dispose();
            }
            catch { };
        }
    }
    //class ATHelper : Helper
    //{
    //    public string Path { get; } = "AT连接";
    //    public string Name { get; } = "AT连接";
    //    public Action<Bitmap, MoveCategory>? SuccessCallBack { get; set; }
    //    public Action<string>? FailCallBack { get; set; }

    //    public string LocalIP { get; set; } = string.Empty;

    //    public string RemoteIP { get; set; } = string.Empty;

    //    private TcpClient? Client;

    //    private string deviceName = "null";

    //    public ATHelper(string localIP, string remoteIP)
    //    {
    //        this.LocalIP = localIP;
    //        this.RemoteIP = remoteIP;

    //        Initialize();
    //    }

    //    public async void Initialize()
    //    {
    //        await Task.Run(() =>
    //        {
    //            try
    //            {
    //                this.Client = new TcpClient(this.RemoteIP, 1024);
    //                ConnectAsync(this.Client);
    //            }
    //            catch (Exception ex)
    //            {
    //                MessageBox.ShowAsync(ex.ToString());
    //            }
    //        });
    //    }


    //    private void ConnectAsync(TcpClient client)
    //    {
    //        _ = Task.Run(async () =>
    //        {
    //            var stream = client.GetStream();
    //            while (true)
    //            {
    //                try
    //                {
    //                    Thread.Sleep(50);
    //                    var data = await Stick.ReadPackAsync(stream);

    //                    switch (data.Key)
    //                    {
    //                        case "init":
    //                        {
    //                            this.deviceName = data.Description;
    //                            break;
    //                        }
    //                        case "LayoutDump_success":
    //                        {
    //                            using var ms = new MemoryStream(data.Buffer);
    //                            var imgLen = ms.ReadInt32();
    //                            var imgBytes = new byte[imgLen];
    //                            ms.Read(imgBytes);
    //                            var jsLen = ms.ReadInt32();
    //                            var jsBytes = new byte[jsLen];
    //                            ms.Read(jsBytes);

    //                            var sKBitmap = SKBitmap.Decode(imgBytes);
    //                            var pxFormat = sKBitmap.ColorType == SKColorType.Rgba8888 ? PixelFormat.Rgba8888 : PixelFormat.Bgra8888;
    //                            var bitmap = new Bitmap(pxFormat, AlphaFormat.Opaque, sKBitmap.GetPixels(), new PixelSize(sKBitmap.Width, sKBitmap.Height), new Vector(96, 96), sKBitmap.RowBytes);

    //                            var js = Encoding.UTF8.GetString(jsBytes);
    //                            var layoutInfo = JsonConvert.DeserializeObject<MoveCategory>(js);

    //                            if (bitmap is not null && layoutInfo is not null)
    //                            {
    //                                this.SuccessCallBack?.Invoke(bitmap, layoutInfo);
    //                            }
    //                            break;
    //                        }
    //                        case "LayoutDump_fail":
    //                        {
    //                            this.FailCallBack?.Invoke(data.Description);
    //                            break;
    //                        }
    //                    }
    //                }
    //                catch (Exception ex)
    //                {
    //                    this.FailCallBack?.Invoke(ex.ToString());
    //                    return;
    //                }
    //            }
    //        });
    //    }

    //    public async Task<ObservableCollection<string>> List()
    //    {
    //        return await Task.Run(() =>
    //        {
    //            var result = new ObservableCollection<string>
    //            {
    //                 this.deviceName
    //            };
    //            return result;
    //        });
    //    }

    //    public void LayoutDump(int Index)
    //    {
    //        if (this.Client == null) throw new Exception("tcp未连接!");
    //        if (!this.Client.Connected) throw new Exception("tcp已断开连接");

    //        try
    //        {
    //            var stream = this.Client.GetStream();
    //            var pack = Stick.MakePackData("layoutDump");
    //            stream.Write(pack);
    //        }
    //        catch (Exception ex)
    //        {
    //            MessageBox.ShowAsync(ex.Message);
    //        }
    //    }

    //    public void Dispose()
    //    {
    //        try
    //        {
    //            this.Client?.Close();
    //            this.Client?.Dispose();
    //            GC.SuppressFinalize(this);
    //        }
    //        catch { };
    //    }
    //}
}
